#include "component.h"
#include "device.h"
#include "button.h"

#define BUTTON_LOG(format, ...)  __OSAL_LOG("[button.c] " C_GREEN format C_NONE"\r\n", ##__VA_ARGS__)

#define EVENT_BUTTON_SCAN    		0x00000001
#define EVENT_BUTTON_READVERSION    0x00000002

static RingBufferHandle_t rbHandle = NULL;

static uint32_t buttont_flag = UINT32_FLAG;
static uint8_t read_version_success = 0;
static void Button_CallbackPX(VirtualHardware_enum_t dev, void *data, uint32_t len)
{
    ButtonMsg_t button = {(UserAction_enum_t)0};
    
	button.action = (UserAction_enum_t)0xFF;
	button.times = 0xFF;
    memcpy(button.name, data, 4);

	OSAL_RingBufferWrite(rbHandle, &button);

    /* 创建ISR事件 */
    OSAL_EventCreateFromISR(COMP_BUTTON);
    read_version_success = 1;
}

/**
  * @brief  按钮状态改变
  * @note   检测到端口有动作就会调用该函数
  *         该函数会在中断里面以回调的形式调用
  *         
  * @param  name：端口名称
  * @param  status：端口状态
  * @param  times：连按次数
  */
static void Button_StatusChange(char *name, uint8_t status, uint8_t times)
{
    ButtonMsg_t button;

	/* 按钮动作暂存缓存区 */
	strcpy(button.name, name);
	button.action = status;
	button.times = times;
	OSAL_RingBufferWrite(rbHandle, &button);
    /* 创建ISR事件 */
    OSAL_EventCreateFromISR(COMP_BUTTON);
}


/**
  * @brief  按钮初始化
  *         
  * @note   定义按钮端口数据，并初始化端口
  */
static void Button_Init(void)
{
    if (rbHandle != NULL)
    {
        return;
    }

    InputPort_stu_t button_list[] = {
        {"BUT_RESET", vPIN_B10, INPUT_PORT_LOGIC_LOW, INPUT_PORT_FUNC_MULTI},  //RESET  恢复出厂键
        {"BUT_CLOSE", vPIN_B11, INPUT_PORT_LOGIC_LOW, INPUT_PORT_FUNC_MULTI},  //CLOSE  关锁键（单机关锁、双击开锁、长按反锁）
        {"BUT_OPEN", vPIN_B12, INPUT_PORT_LOGIC_LOW, INPUT_PORT_FUNC_MULTI},    //OPEN   开锁键（双击开锁）
        {"BUT_TOUCH1", vPIN_I6, INPUT_PORT_LOGIC_HIGH, INPUT_PORT_FUNC_SINGLE}, //后板触摸pad1
        {"BUT_TOUCH2", vPIN_I7, INPUT_PORT_LOGIC_HIGH, INPUT_PORT_FUNC_SINGLE}, //后板触摸pad2
        {"BUT_HALL_KN", vPIN_I10, INPUT_PORT_LOGIC_HIGH, INPUT_PORT_FUNC_SINGLE}, //后板开门检测的hall
    #if defined(DAMAGE_NC) //常闭开关(Normally closed)
        {"BUT_DAMAGE", vPIN_B13, INPUT_PORT_LOGIC_HIGH, INPUT_PORT_FUNC_SINGLE}, //DAMAGE 防撬按键
    #else
        {"BUT_DAMAGE", vPIN_B13, INPUT_PORT_LOGIC_LOW, INPUT_PORT_FUNC_SINGLE}, //DAMAGE 防撬按键
    #endif
        // {"BUT_M_KEY", vPIN_B14, INPUT_PORT_LOGIC_LOW, INPUT_PORT_FUNC_SINGLE},  //M-KEY  机械钥匙
        {"BUT_D_SENSOR", vPIN_I13, INPUT_PORT_LOGIC_LOW, INPUT_PORT_FUNC_SINGLE},  //红外距离传感器TRWO1090
        {"BUT_COVER_CHECK", vPIN_B15, INPUT_PORT_LOGIC_HIGH, INPUT_PORT_FUNC_SINGLE},  //滑盖
        {"BUT_Extend_INT", vPIN_I2, INPUT_PORT_LOGIC_HIGH, INPUT_PORT_FUNC_SINGLE},  //扩展模块
        {"BUT_Doorbell", vPIN_B29, INPUT_PORT_LOGIC_HIGH, INPUT_PORT_FUNC_SINGLE},  //单独门铃
        {"BUT_BLE_CFG", vPIN_B16, INPUT_PORT_LOGIC_LOW, INPUT_PORT_FUNC_MULTI},    //蓝牙配置按键
        {"BUT_HALL1", vPIN_B30, INPUT_PORT_LOGIC_LOW, INPUT_PORT_FUNC_SINGLE},    //门磁霍尔
        {"BUT_HALL2", vPIN_B31, INPUT_PORT_LOGIC_LOW, INPUT_PORT_FUNC_SINGLE},    //门磁霍尔
        {"BUT_SET", vPIN_B9, INPUT_PORT_LOGIC_LOW, INPUT_PORT_FUNC_SINGLE},    //蓝牙设置键
        {"SHOW_KEY", vPIN_B32, INPUT_PORT_LOGIC_LOW, INPUT_PORT_FUNC_SINGLE},    //显示屏按键
        {"HOME_KEY", vPIN_B34, INPUT_PORT_LOGIC_LOW, INPUT_PORT_FUNC_MULTI},  //Homekit键
    };

    /* 注册端口 */
    InputPort_Registered(button_list, OSAL_LENGTH(button_list), Button_StatusChange);
    InputPort_EnableProt("BUT_RESET");//
    InputPort_EnableProt("BUT_CLOSE");
    InputPort_EnableProt("BUT_OPEN");
    InputPort_EnableProt("BUT_DAMAGE");
    // InputPort_EnableProt("BUT_M_KEY");
    InputPort_EnableProt("BUT_TOUCH1");
    InputPort_EnableProt("BUT_TOUCH2");
    InputPort_EnableProt("BUT_HALL_KN");
    InputPort_EnableProt("BUT_D_SENSOR");
    InputPort_EnableProt("BUT_COVER_CHECK");
    InputPort_EnableProt("BUT_Extend_INT");
    InputPort_EnableProt("BUT_Doorbell");
    InputPort_EnableProt("BUT_BLE_CFG");
    InputPort_EnableProt("BUT_HALL1");
    InputPort_EnableProt("BUT_HALL2");
    InputPort_EnableProt("BUT_SET");
    InputPort_EnableProt("SHOW_KEY");
    InputPort_EnableProt("HOME_KEY");
    /* 复位键设置成长按5s生效 */
    InputPort_SetProtLongPressTime("BUT_RESET", 5000);

    InputPort_SetProtLongPressTime("BUT_OPEN", 3000);
    InputPort_SetProtLongPressTime("BUT_BLE_CFG",3000);
    InputPort_SetProtLongPressTime("BUT_SET", 3000); // SET键长按3s生效

#ifdef INDUCTIVE_HANDLE
    InputPort_SetProtTimeInterval("BUT_CLOSE",5,50);
    InputPort_SetProtLongPressTime("BUT_CLOSE", 2000);
#else
    InputPort_SetProtLongPressTime("BUT_CLOSE", 3000);    
#endif

    /* 创建环形缓存（暂存按钮状态） */
    rbHandle = OSAL_RingBufferCreate(10, sizeof(ButtonMsg_t));

    Device_RegisteredCB(vPIN_PX, Button_CallbackPX);
}


uint32_t wakup_pin_flag;

/**
  * @brief  按钮任务函数
  *
  * @note
  *         
  * @param  event：当前任务的所有事件
  *
  * @return 返回未处理的事件
  */
static uint32_t Button_Task(uint32_t event)
{
    static uint8_t flag_first = 0;
    static uint8_t flag_num = 0;
	/* 系统启动事件 */
	if (event & EVENT_SYS_START)
	{
		BUTTON_LOG("Button task start\r\n");
		
        Button_Init();
    #ifdef BLE_APP_TSPPS_CONNECT_MAX
    if(flag_first == 0)
    {
        OSAL_EventRepeatCreate(COMP_BUTTON, EVENT_BUTTON_READVERSION, 50, EVT_PRIORITY_MEDIUM);     //读取的事件的间隔至少为25ms以上
        flag_first =1;
    }
    #endif
#if defined(HI3816_CHIP_PLATFORM) || defined (BL602_CHIP_PLATFORM) || defined(ESP32_CHIP_PLATFORM)
        OSAL_EventRepeatCreate(COMP_BUTTON, EVENT_BUTTON_SCAN, 10, EVT_PRIORITY_MEDIUM);
#endif
		return ( event ^ EVENT_SYS_START );
	}

	if (event & EVENT_BUTTON_READVERSION)       //用于读取感应把手的版本号，上电前3秒执行
	{
        BUTTON_LOG("read version\r\n");
        Device_DelayMs(2);
        Device_Write(vPIN_I6,NULL,0,PIN_MODE_OD_DRIVE);
        Device_Write(vPIN_I6,NULL,0,1);
        Device_DelayMs(4);                      //这个时间不能超过8ms，不然能被组件检测到拉高和拉低，持续时间太长也会导致连续发送2次
        Device_Write(vPIN_I6,NULL,0,0);
        Device_DelayMs(21);                     //拉高和延时至少为25ms，让发版本的时候不运行其他的任务，避免被其他的干扰
        Device_Write(vPIN_I6,NULL,0,PIN_MODE_INPUT_PULLDOWN);
        flag_num++;
        if((read_version_success ==1)||(flag_num > 10))    //读取成功就删除事件，失败就继续读取
        {
            printf("\r\ndele EVENT_BUTTON_SCAN\r\n");
            OSAL_EventDelete(COMP_BUTTON,EVENT_BUTTON_READVERSION);
        }
		return ( event ^ EVENT_BUTTON_READVERSION );
	}

	/* 系统休眠事件 */
	if (event & EVENT_SYS_SLEEP)
	{
        void test_1(void);
        test_1();
		BUTTON_LOG("Button task sleep\r\n");
        Device_Disable(vPIN_B13);
        Device_Disable(vPIN_I10);
        Device_Disable(vPIN_I6);
        Device_Disable(vPIN_I7);
        Device_Disable(vPIN_B30);
        Device_Disable(vPIN_B31);
        Device_Disable(vPIN_B11);
        Device_Disable(vPIN_B12);
        Device_Disable(vPIN_B32);
        //Device_Disable(vPIN_B34);
		return ( event ^ EVENT_SYS_SLEEP );
	}

	/* 系统中断事件 */
	if (event & EVENT_SYS_ISR)
	{
        ButtonMsg_t button;

        while (OSAL_RingBufferRead(rbHandle, &button) == SUCCESS)
        {
            BUTTON_LOG("button: %s\r\n", button.name);
			if(Get_lockCalibFlag_Status()==SET)
			{
				if (strcmp("BUT_CLOSE", button.name) == 0) wakup_pin_flag|=KEY_OPEN_CLOSE_PIN; //上锁键
				OSAL_MessagePublish(&button, sizeof(button));
			}
        }
		return ( event ^ EVENT_SYS_ISR );
	}

#if defined(HI3816_CHIP_PLATFORM) || defined (BL602_CHIP_PLATFORM) || defined(ESP32_CHIP_PLATFORM)
	if (event & EVENT_BUTTON_SCAN)
	{
        InputPort_Scan(0X0F, 10);
		return ( event ^ EVENT_BUTTON_SCAN );
	}
#endif

	return 0;
}
COMPONENT_TASK_EXPORT(COMP_BUTTON, Button_Task, 0);

/**
  * @brief  BUTTON唤醒逻辑处理
  * @param  
  * @return 
  */
static int32_t Button_WakeHandle(uint32_t dev)
{
#if defined(HI3816_CHIP_PLATFORM) || defined (BL602_CHIP_PLATFORM) || defined(ESP32_CHIP_PLATFORM)
    if (dev == vPIN_B32)
    {
        for (int i=0; i<10; i++)
        {
            InputPort_Scan(0X0F, 1);
            OSAL_DelayUs(500);
        }
    }
#endif
    if (dev == vPIN_B13)
    {
        BUTTON_LOG("Button_WakeHandle vPIN_B13");
        for (int i = 0; i < 10; i++)
        {
            InputPort_Scan(0X0F, 1);
            OSAL_DelayUs(500);
        }
        if (Device_Read(vPIN_B13, NULL, 0, 0))
        {
            BUTTON_LOG("GPIO_FALLING_EDGE");
             Device_Disable(vPIN_B13);
            return 0;
        }
        else
        {
            BUTTON_LOG("GPIO_RISING_EDGE");
            return 1;
        }
    }
    /* RAM数据未丢失，inputport会唤醒系统，这里wakehandle不用做任何处理 */
    if (buttont_flag == UINT32_FLAG)
    {
        return -1;
    }

    /* RAM数据丢失了，PIN设备唤醒，要做消抖判断 */
    return dev; //TODO消抖
}
#if defined(HI3816_CHIP_PLATFORM)
COMPONENT_WAKEUP_EXPORT(COMP_BUTTON, Button_WakeHandle, vPIN_B32);//显示屏按键
#else
COMPONENT_WAKEUP_EXPORT(COMP_BUTTON, Button_WakeHandle, vPIN_B13);//防撬
COMPONENT_WAKEUP_EXPORT(COMP_BUTTON, Button_WakeHandle, vPIN_B11);//CLOSE
COMPONENT_WAKEUP_EXPORT(COMP_BUTTON, Button_WakeHandle, vPIN_B12);//open
COMPONENT_WAKEUP_EXPORT(COMP_BUTTON, Button_WakeHandle, vPIN_I13);//红外接近中断
COMPONENT_WAKEUP_EXPORT(COMP_BUTTON, Button_WakeHandle, vPIN_B10);//reset回复出厂
COMPONENT_WAKEUP_EXPORT(COMP_BUTTON, Button_WakeHandle, vPIN_B15);//滑盖
COMPONENT_WAKEUP_EXPORT(COMP_BUTTON, Button_WakeHandle, vPIN_I2);//扩展模块
COMPONENT_WAKEUP_EXPORT(COMP_BUTTON, Button_WakeHandle, vPIN_B29);//doorbell
COMPONENT_WAKEUP_EXPORT(COMP_BUTTON, Button_WakeHandle, vPIN_B16);//蓝牙配网键
COMPONENT_WAKEUP_EXPORT(COMP_BUTTON, Button_WakeHandle, vPIN_B30);//门磁霍尔感应1
COMPONENT_WAKEUP_EXPORT(COMP_BUTTON, Button_WakeHandle, vPIN_B31);//门磁霍尔感应2
COMPONENT_WAKEUP_EXPORT(COMP_BUTTON, Button_WakeHandle, vPIN_B9);//门磁霍尔感应2
COMPONENT_WAKEUP_EXPORT(COMP_BUTTON, Button_WakeHandle, vPIN_B34);//Homekit
#endif
char import_kos_button;
